#include "../server.hpp"
#include <iostream>

// test for channel&Epoller
// void HandleClose(Channel *chl)
// {
//     std::cout << "close: " << chl->Fd() << std::endl;
//     chl->Remove(); // 移除监控
//     delete chl;
// }
// void HandleRead(Channel *chl) {
//     int fd = chl->Fd();
//     char buf[1024] = {0};
//     int ret = recv(fd, buf, 1023, 0);
//     if (ret <= 0) {
//         return HandleClose(chl); // 关闭释放
//     }
//     chl->MonitorWrite(); // 启动写监控
//     std::cout << buf << std::endl;
// }
// void HandleWrite(Channel *chl) {
//     int fd = chl->Fd();
//     const char *data = "天气还不错!!";
//     int ret = send(fd, data, strlen(data), 0);
//     if (ret < 0) {
//         HandleClose(chl); // 关闭释放
//     }
//     chl->UnMonitorWrite(); // 关闭写监控
// }
// void HandleError(Channel *chl) {
//     HandleClose(chl); // 关闭释放
// }
// void HandleEvent(Channel *chl) {
//     std::cout << "有了一个事件!! \n";
// }
// void Acceptor(Epoller* ep, Channel* lst)
// {
//     int fd = lst->Fd();
//     int newfd = accept(fd, nullptr, nullptr);
//     if (newfd < 0) { return; }
//     Channel *channel1 = new Channel(newfd,ep);
//     channel1->SetReadCallBack(std::bind(HandleRead, channel1)); // 为通信套接字设置可读事件的回调函数
//     channel1->SetWriteCallBack(std::bind(HandleWrite, channel1)); // 可写事件的回调函数
//     channel1->SetCloseCallBack(std::bind(HandleClose, channel1)); // 关闭事件的回调函数
//     channel1->SetErrorCallBack(std::bind(HandleError, channel1)); // 错误事件的回调函数
//     channel1->SetEventCallBack(std::bind(HandleEvent, channel1)); // 任意事件的回调函数
//     channel1->MonitorRead();
// }
// int main()
// {
//     Socket server;
//     server.CreateServer(8888);
//     Epoller ep;
//     Channel chl(server.Fd(),&ep);
//     chl.SetReadCallBack(std::bind(Acceptor, &ep, &chl));
//     chl.MonitorRead();
//     while(1)
//     {
//         std::vector<Channel*> actives;
//         ep.EpollerWait(&actives);
//         for(auto e:actives)
//         {
//             e->Hander();
//         }
//     }
//     server.Close();
//     return 0;
// }

// test for Epoller&EventLoop
// void HandleClose(Channel *chl)
// {
//     std::cout << "close: " << chl->Fd() << std::endl;
//     chl->Remove(); // 移除监控
//     delete chl;
// }
// void HandleRead(Channel *chl) {
//     int fd = chl->Fd();
//     char buf[1024] = {0};
//     int ret = recv(fd, buf, 1023, 0);
//     if (ret <= 0) {
//         return HandleClose(chl); // 关闭释放
//     }
//     chl->MonitorWrite(); // 启动写监控
//     std::cout << buf << std::endl;
// }
// void HandleWrite(Channel *chl) {
//     int fd = chl->Fd();
//     const char *data = "天气还不错!!";
//     int ret = send(fd, data, strlen(data), 0);
//     if (ret < 0) {
//         HandleClose(chl); // 关闭释放
//     }
//     chl->UnMonitorWrite(); // 关闭写监控
// }
// void HandleError(Channel *chl) {
//     HandleClose(chl); // 关闭释放
// }
// void HandleEvent(Channel *chl) {
//     std::cout << "有了一个事件!! \n";
// }
// void Acceptor(EventLoop* el, Channel* lst)
// {
//     int fd = lst->Fd();
//     int newfd = accept(fd, nullptr, nullptr);
//     if (newfd < 0) { return; }
//     Channel *channel1 = new Channel(newfd,el);
//     channel1->SetReadCallBack(std::bind(HandleRead, channel1)); // 为通信套接字设置可读事件的回调函数
//     channel1->SetWriteCallBack(std::bind(HandleWrite, channel1)); // 可写事件的回调函数
//     channel1->SetCloseCallBack(std::bind(HandleClose, channel1)); // 关闭事件的回调函数
//     channel1->SetErrorCallBack(std::bind(HandleError, channel1)); // 错误事件的回调函数
//     channel1->SetEventCallBack(std::bind(HandleEvent, channel1)); // 任意事件的回调函数
//     channel1->MonitorRead();
// }
// int main()
// {
//     Socket server;
//     server.CreateServer(8888);
//     EventLoop el;
//     Channel chl(server.Fd(),&el);
//     chl.SetReadCallBack(std::bind(Acceptor, &el, &chl));
//     chl.MonitorRead();
//     while(1)
//     {
//         el.Start();
//     }
//     server.Close();
//     return 0;
// }

// test for Epoller&EventLoop&TimeWheel
// void HandleClose(Channel *chl)
// {
//     lg(Info,"close: %d",chl->Fd());
//     chl->Remove(); // 移除监控
//     delete chl;
// }
// void HandleRead(Channel *chl) {
//     int fd = chl->Fd();
//     char buf[1024] = {0};
//     int ret = recv(fd, buf, 1023, 0);
//     if (ret <= 0) {
//         return HandleClose(chl); // 关闭释放
//     }
//     chl->MonitorWrite(); // 启动写监控
//     lg(Info,"%s",buf);
// }
// void HandleWrite(Channel *chl) {
//     int fd = chl->Fd();
//     const char *data = "天气还不错!!";
//     int ret = send(fd, data, strlen(data), 0);
//     if (ret < 0) {
//         HandleClose(chl); // 关闭释放
//     }
//     chl->UnMonitorWrite(); // 关闭写监控
// }
// void HandleError(Channel *chl) {
//     HandleClose(chl); // 关闭释放
// }
// void HandleEvent(EventLoop* el,uint64_t timeid,Channel *chl) {
//     std::cout << "有了一个事件!! \n";
//     el->RefreshTimer(timeid);
// }
// void Acceptor(EventLoop* el, Channel* lst)
// {
//     int fd = lst->Fd();
//     int newfd = accept(fd, nullptr, nullptr);
//     if (newfd < 0) { return; }
//     uint64_t timeid=rand()%10000; // 定时器id
//     Channel *channel1 = new Channel(newfd,el);
//     channel1->SetReadCallBack(std::bind(HandleRead, channel1)); // 为通信套接字设置可读事件的回调函数
//     channel1->SetWriteCallBack(std::bind(HandleWrite, channel1)); // 可写事件的回调函数
//     channel1->SetCloseCallBack(std::bind(HandleClose, channel1)); // 关闭事件的回调函数
//     channel1->SetErrorCallBack(std::bind(HandleError, channel1)); // 错误事件的回调函数
//     channel1->SetEventCallBack(std::bind(HandleEvent, el,timeid,channel1)); // 任意事件的回调函数
//     channel1->MonitorRead();
//     el->AddTimer(timeid,std::bind(HandleClose,channel1),5);
// }
// int main()
// {
//     srand(time(nullptr));
//     Socket server;
//     server.CreateServer(8888);
//     EventLoop el;
//     Channel chl(server.Fd(),&el);
//     chl.SetReadCallBack(std::bind(Acceptor, &el, &chl));
//     chl.MonitorRead();
//     while(1)
//     {
//         el.Start();
//     }
//     server.Close();
//     return 0;
// }

// test for Connection
// using PtrConnection = std::shared_ptr<Connection>;
// uint64_t cnn_id=0; 
// std::unordered_map<uint64_t,PtrConnection> cnns;
// void DestroyConnection(const PtrConnection& cnn) {cnns.erase(cnn->Id());}
// void OnConnected(const PtrConnection& cnn) {lg(Debug,"NEWCONNECTION:%p",cnn.get());}
// void OnMessage(const PtrConnection& cnn,Buffer* bf)
// {
//     lg(Debug,"%s",bf->ReadPos());
//     bf->MoveReadOffset(bf->ReadableSize());
//     std::string str="Hello World!!\n";
//     cnn->Send(str.c_str(),str.size());
//     // cnn->Shutdown();
// }
// 
// void Acceptor(EventLoop* el, Channel* lst)
// {
//     int fd = lst->Fd();
//     int newfd = accept(fd, nullptr, nullptr);
//     if (newfd < 0) return; 
//     std::cout<<"fd: "<<fd<<" new fd: "<<newfd<<std::endl;
//     cnn_id++;
//     PtrConnection cnn(new Connection(cnn_id,newfd,el));
//     cnn->SetConnectedCallBack(std::bind(OnConnected,std::placeholders::_1));
//     cnn->SetMessageCallBack(std::bind(OnMessage,std::placeholders::_1,std::placeholders::_2));
//     cnn->SetServerClosedCallBack(std::bind(DestroyConnection,std::placeholders::_1));
// 
//     cnn->SetInactiveRelease(10);
//     cnn->Established();
//     cnns.insert(std::make_pair(cnn_id,cnn));
// }
// int main()
// {
//     Socket server;
//     server.CreateServer(8888);
//     EventLoop el;
//     Channel chl(server.Fd(),&el);
//     chl.SetReadCallBack(std::bind(Acceptor, &el, &chl));
//     chl.MonitorRead();
//     while(1)
//     {
//         el.Start();
//     }
//     server.Close();
//     return 0;
// }

// test for Acceptor
// using PtrConnection = std::shared_ptr<Connection>;
// uint64_t cnn_id=0; 
// EventLoop loop;
// std::unordered_map<uint64_t,PtrConnection> cnns;
// void DestroyConnection(const PtrConnection& cnn) {cnns.erase(cnn->Id());}
// void OnConnected(const PtrConnection& cnn) {lg(Debug,"NEWCONNECTION: %p",cnn.get());}
// void OnMessage(const PtrConnection& cnn,Buffer* bf)
// {
//     lg(Debug,"%s",bf->ReadPos());
//     bf->MoveReadOffset(bf->ReadableSize());
//     std::string str="Hello World!!!\n";
//     cnn->Send(str.c_str(),str.size());
//     cnn->Shutdown();
// }
// 
// void NewConection(int newfd)
// {
//     cnn_id++;
//     PtrConnection cnn(new Connection(cnn_id,newfd,&loop));
//     cnn->SetConnectedCallBack(std::bind(OnConnected,std::placeholders::_1));
//     cnn->SetMessageCallBack(std::bind(OnMessage,std::placeholders::_1,std::placeholders::_2));
//     cnn->SetServerClosedCallBack(std::bind(DestroyConnection,std::placeholders::_1));
// 
//     cnn->SetInactiveRelease(5);
//     cnn->Established();
//     cnns.insert(std::make_pair(cnn_id,cnn));
// }
// 
// int main()
// {
//     Acceptor acpt(&loop,8888);
//     acpt.SetNewConnectionCallBack(std::bind(NewConection,std::placeholders::_1));
//     acpt.Listen();
//     while(1)
//     {
//         loop.Start();
//     }
//     return 0;
// }

// test for LoopThread
// using PtrConnection = std::shared_ptr<Connection>;
// EventLoop base_loop;
// uint64_t cnn_id=0; 
// std::vector<LoopThread> threads(2);
// int next_loop=0;
// 
// std::unordered_map<uint64_t,PtrConnection> cnns;
// void DestroyConnection(const PtrConnection& cnn) {cnns.erase(cnn->Id());}
// void OnConnected(const PtrConnection& cnn)
// {
//     lg(Debug,"Main Thread: %p, NEWCONNECTION: %p",(void*)pthread_self(),cnn.get());
// }
// void OnMessage(const PtrConnection& cnn,Buffer* bf)
// {
//     lg(Debug,"Worker Thread: %p, %s",(void*)pthread_self(),bf->ReadPos());
//     bf->MoveReadOffset(bf->ReadableSize());
//     std::string str="Hello World!!!\n";
//     cnn->Send(str.c_str(),str.size());
//     // cnn->Shutdown();
// }
// 
// void NewConection(int newfd)
// {
//     lg(Debug,"Main Thread: %p",(void *)pthread_self());
//     cnn_id++;
//     next_loop=(next_loop+1)%2;
//     PtrConnection cnn(new Connection(cnn_id,newfd,threads[next_loop].GetLoop()));
//     cnn->SetConnectedCallBack(std::bind(OnConnected,std::placeholders::_1));
//     cnn->SetMessageCallBack(std::bind(OnMessage,std::placeholders::_1,std::placeholders::_2));
//     cnn->SetServerClosedCallBack(std::bind(DestroyConnection,std::placeholders::_1));
// 
//     cnn->SetInactiveRelease(5);
//     cnn->Established();
//     cnns.insert(std::make_pair(cnn_id,cnn));
// }
// 
// int main()
// {
//     Acceptor acpt(&base_loop,8888);
//     acpt.SetNewConnectionCallBack(std::bind(NewConection,std::placeholders::_1));
//     acpt.Listen();
//     base_loop.Start();
//     return 0;
// }

// test for LoopThreadPool
// using PtrConnection = std::shared_ptr<Connection>;
// EventLoop base_loop;
// uint64_t cnn_id=0; 
// LoopThreadPool* ltp;
// 
// std::unordered_map<uint64_t,PtrConnection> cnns;
// void DestroyConnection(const PtrConnection& cnn) {cnns.erase(cnn->Id());}
// void OnConnected(const PtrConnection& cnn)
// {
//     lg(Debug,"Main Thread: %p, NEWCONNECTION: %p",(void*)pthread_self(),cnn.get());
// }
// void OnMessage(const PtrConnection& cnn,Buffer* bf)
// {
//     lg(Debug,"Worker Thread: %p, %s",(void*)pthread_self(),bf->ReadPos());
//     bf->MoveReadOffset(bf->ReadableSize());
//     std::string str="Hello World!!!\n";
//     cnn->Send(str.c_str(),str.size());
//     // cnn->Shutdown();
// }
// 
// void NewConection(int newfd)
// {
//     lg(Debug,"Main Thread: %p",(void *)pthread_self());
//     cnn_id++;
//     PtrConnection cnn(new Connection(cnn_id,newfd,ltp->NextLoop()));
//     cnn->SetConnectedCallBack(std::bind(OnConnected,std::placeholders::_1));
//     cnn->SetMessageCallBack(std::bind(OnMessage,std::placeholders::_1,std::placeholders::_2));
//     cnn->SetServerClosedCallBack(std::bind(DestroyConnection,std::placeholders::_1));
// 
//     cnn->SetInactiveRelease(5);
//     cnn->Established();
//     cnns.insert(std::make_pair(cnn_id,cnn));
// }
// 
// int main()
// {
//     ltp=new LoopThreadPool(&base_loop);
//     ltp->SetThreadPoolSize(2); 
//     ltp->Init();
//     Acceptor acpt(&base_loop,8888);
//     acpt.SetNewConnectionCallBack(std::bind(NewConection,std::placeholders::_1));
//     acpt.Listen();
//     base_loop.Start();
//     return 0;
// }

// test for TcpServer
using PtrConnection = std::shared_ptr<Connection>;

std::unordered_map<uint64_t,PtrConnection> cnns;
void OnConnected(const PtrConnection& cnn) {lg(Debug,"NEW CONNECTION: %p",cnn.get());}
void OnClose(const PtrConnection& cnn) {lg(Debug,"Close CONNECTION: %p",cnn.get());}
void OnMessage(const PtrConnection& cnn,Buffer* bf)
{
    lg(Debug,"Worker Thread: %p, %s",(void*)pthread_self(),bf->ReadPos());
    cnn->Send(bf->ReadPos(),bf->ReadableSize());
    bf->MoveReadOffset(bf->ReadableSize());
    // std::string str="Hello World!!!\n";
    // cnn->Send(str.c_str(),str.size());
    // cnn->Shutdown();
}

int main()
{
    TcpServer svr(8888);
    svr.SetThreadPoolSize(2);
    svr.SetInactiveRelease(5);
    svr.SetConnectedCallBack(OnConnected);
    svr.SetMessageCallBack(OnMessage);
    svr.SetClosedCallBack(OnClose);
    svr.Start();
    return 0;
}